using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using Shrapnel.Areas;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using System.Runtime.Serialization;

namespace Shrapnel
{
	/// <summary>
	/// Our base class for anything that should be visualized in our control
	/// </summary>
	[DataContract()]
	public abstract class Element
	{
		/// <summary>
		/// The area this element occupies
		/// </summary>
		[DataMember(Name="OccupiedArea")]
		private Area occupiedArea = new Area();

		/// <summary>
		/// Are we selected? Are we that popular?
		/// </summary>	
		[DataMember(Name="Selected")]
		private bool isSelected = false;

		/// <summary>
		/// The layer we are placed on
		/// </summary>
		[DataMember(Name = "ParentLayer")]
		private Layer parentLayer = null;

		/// <summary>
		/// An object attached to this element by the user. 
		/// </summary>
		private IUserObject userObject = null;


		/// <summary>
		/// Access to the occupied area of this element
		/// </summary>
		public Area OccupiedArea
		{
			get { return occupiedArea; }
		}

		/// <summary>
		/// Are we selected? Are we that popular?
		/// </summary>
		public bool IsSelected 
		{
			get { return isSelected; }
			set { isSelected = value; }
		}

		/// <summary>
		/// The layer we are placed on
		/// </summary>
		public Layer ParentLayer
		{
			get { return parentLayer; }
			set { parentLayer = value; }
		}

		/// <summary>
		/// Position in world space of the top left corner of this element's area
		/// </summary>
		public PointF Position
		{
			get { return occupiedArea.TopLeftPosition; }
			set { MoveToPosition(value); }
		}

		/// <summary>
		/// An object attached to this element by the user. 
		/// </summary>
		public IUserObject UserObject
		{
			get { return userObject; }
			set { userObject = value;  }
		}


		/// <summary>
		/// Draw this element for the given view 
		/// </summary>
		/// <param name="graphics">Graphics object to use for drawing</param>
		/// <param name="viewState">View to use</param>
		public abstract void Draw(Graphics graphics, ViewState viewState);


		/// <summary>
		/// Move our element to the provided position, so that our area's topleftposition is equal to that position.
		/// </summary>
		/// <param name="position">Position to move to in world space</param>
		protected virtual void MoveToPosition(PointF position)
		{
			occupiedArea.MoveToPosition(position);			
		}


		/// <summary>
		/// Calculate the bounding rectangle for this element
		/// </summary>
		/// <returns>Bounding rectangle in world coordinates</returns>
		public virtual BoundingBox GetBoundingBox()
		{
			return occupiedArea.AreaBoundingBox;
		}

		/// <summary>
		/// See if we overlap with a box
		/// </summary>
		/// <param name="rectangle"></param>
		/// <returns></returns>
		public virtual bool OverlapsWith(BoundingBox bbox)
		{
			return occupiedArea.OverlapsWith(bbox);
		}
	}
}
